//******************************************************************
//******************************************************************
//**********          ANts Peer To Peer Sources        *************
//
// ANts P2P realizes a third generation P2P net. It protects your
// privacy while you are connected and makes you not trackable, hiding
// your identity (ip) and crypting everything you are sending/receiving
// from others.

// Copyright (C) 2004  Roberto Rossi

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

package ants.p2p.query.security;

import ants.p2p.utils.encoding.*;
import java.io.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public class AsymmetricProvider {
  PublicHeader ph = null;
  MessageHeader mh = null;

  public static final int RSAKEYSIZE = 1024;
  public static final int RSACERTAINTY = 10;

  public AsymmetricProvider(PublicHeader ph) throws Exception{
    this.ph=ph;
    ph.generateSessionKey();
  }

  public AsymmetricProvider(boolean generate) throws Exception{
    if(generate){
      this.mh = new MessageHeader(RSAKEYSIZE, RSACERTAINTY);
      this.storeMessageHeader();
    }else{
      this.loadMessageHeader();
    }
  }

  public void storeMessageHeader() throws Exception{
    if(this.mh!=null){
      MessageHeaderRepository.storeMessageHeader(this.mh);
    }
    else
      throw new Exception("Null Message Header");
  }

  public void loadMessageHeader() throws IOException, ClassNotFoundException{
    this.mh = MessageHeaderRepository.loadMessageHeader();
  }


  public PublicHeader getPublicHeader(){
    if(mh != null)
      return this.mh.generatePublicHeader();
    else
      return this.ph;
  }

  public String encryptMessage(String message){
    if(this.ph!=null){
      return Base16.toHexString(SimmetricProvider.encrypt(ph.
          getBase16SessionKey(), message.getBytes()));
    }
    else{
      return Base16.toHexString(SimmetricProvider.encrypt(mh.generatePublicHeader().
          getBase16SessionKey(), message.getBytes()));
    }
  }

  public String decryptMessage(String message, String sessionKey) throws Exception{
    if(this.mh!=null){
      return new String( (SimmetricProvider.decrypt(sessionKey,
          Base16.fromHexString(message))));
    }
    else
      throw new Exception("Null Message Header");
  }

  /*public Cipher getEncCipher(String plainSessionKey) throws Exception{
    SecretKeySpec skeySpec = new SecretKeySpec(Base16.fromHexString(plainSessionKey),
                                               SimmetricProvider.cipher);
    Cipher cipher = Cipher.getInstance(SimmetricProvider.cipher);
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    return cipher;
  }*/

  public Cipher getDecCipher(String encryptedSessionKey) throws Exception{
    String sessionKey = this.mh.decryptSessionKey(encryptedSessionKey);
    SecretKeySpec skeySpec = new SecretKeySpec(Base16.fromHexString(sessionKey),
                                               SimmetricProvider.cipher);
    Cipher cipher = Cipher.getInstance(SimmetricProvider.cipher);
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    return cipher;
  }

  /*
  public static void main(String args[]){
    try{
      AsymmetricProvider client = new AsymmetricProvider(true);
      client.storeMessageHeader();
      AsymmetricProvider server = new AsymmetricProvider(client.getPublicHeader());
      client = new AsymmetricProvider(false);
      String encrypted = server.encryptMessage("Ciao a tutti");
      String decrypted = client.decryptMessage(encrypted,server.getPublicHeader().getBase64SessionKey());
      System.out.println(encrypted);
      System.out.println(decrypted);
    }catch(Exception e){e.printStackTrace();}
  }
  */
}

class MessageHeaderRepository{
  static MessageHeader mh = null;

  public static void storeMessageHeader(MessageHeader mh){
    MessageHeaderRepository.mh = mh;
  }

  public static MessageHeader loadMessageHeader(){
    return MessageHeaderRepository.mh;
  }
}
